package com.example.im.xmpp

import android.content.Context
import android.net.ConnectivityManager
import com.example.im.app.ImApplication
import com.example.im.bean.UserRoom
import com.example.im.common.Constants
import com.example.im.db.DatabaseStorage
import com.example.im.utils.LogUtils
import com.example.im.utils.RandomUntil

import org.jivesoftware.smack.AbstractXMPPConnection
import org.jivesoftware.smack.ConnectionConfiguration
import org.jivesoftware.smack.XMPPConnection
import org.jivesoftware.smack.chat2.ChatManager
import org.jivesoftware.smack.filter.AndFilter
import org.jivesoftware.smack.filter.OrFilter
import org.jivesoftware.smack.filter.StanzaTypeFilter
import org.jivesoftware.smack.packet.IQ
import org.jivesoftware.smack.packet.Message
import org.jivesoftware.smack.packet.Presence
import org.jivesoftware.smack.roster.Roster
import org.jivesoftware.smack.roster.RosterEntry
import org.jivesoftware.smack.roster.packet.RosterPacket
import org.jivesoftware.smack.tcp.XMPPTCPConnection
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration
import org.jivesoftware.smackx.bookmarks.BookmarkManager
import org.jivesoftware.smackx.bookmarks.BookmarkedConference
import org.jivesoftware.smackx.iqregister.AccountManager
import org.jivesoftware.smackx.muc.*
import org.jivesoftware.smackx.ping.PingManager
import org.jivesoftware.smackx.search.ReportedData
import org.jivesoftware.smackx.search.UserSearchManager
import org.jivesoftware.smackx.xdata.FormField
import org.jxmpp.jid.impl.JidCreate
import org.jxmpp.jid.parts.Localpart
import org.jxmpp.jid.parts.Resourcepart

import java.net.InetAddress
import java.util.*

class IMConnection : DefaultConnection() {

    private var connection: AbstractXMPPConnection? = null

    private var mRosterManager: Roster? = null

    private var mChatManager: ChatManager? = null

    private var mMucManager: MultiUserChatManager? = null

    private var mBookmarkManager: BookmarkManager? = null

    private var mPingManager: PingManager? = null

    private var mTimerServer: Timer? = null

    private val mMultiUserChatMap = HashMap<String, MultiUserChat>()

    private var wasAuthenticated: Boolean = false

    init {
        initConnection()
    }

    /**
     * 初始化AbstractXMPPConnection
     */
    private fun initConnection() {
        //SmackConfiguration.DEBUG = true
        val config = XMPPTCPConnectionConfiguration.builder()
        //设置主机IP
        config.setHostAddress(InetAddress.getByName(Constants.XMPP_SERVICE_HOST))
        //设置服务器名称
        config.setXmppDomain(Constants.XMPP_SERVICE_DOMAIN)
        //设置端口号
        config.setPort(Constants.XMPP_SERVICE_PORT)
        //设置资源名
        config.setResource(Constants.XMPP_SERVICE_RESOURCE)
        //设置离线状态
        config.setSendPresence(false)
        //设置开启压缩
        config.setCompressionEnabled(true)
        //禁用SSL连接
        config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
        //初始化连接
        connection = XMPPTCPConnection(config.build())
        //连接监听
        connection!!.addConnectionListener(this)
        //过滤iq
        val typeFilter = StanzaTypeFilter(Presence::class.java)
        val andFilter = AndFilter(typeFilter)
        //用户状态监听
        connection!!.addSyncStanzaListener(this, andFilter)

        //启动定时服务发送PING心跳包
        mTimerServer = Timer()
        mTimerServer?.schedule(PingTimerTask(), 0, (1000 * 2).toLong())
    }

    inner class PingTimerTask : TimerTask() {

        override fun run() {
            if (!isNetworkState) {
                LogUtils.e("发送PING：网络连接不可用")
                return
            }

            if (!isAuthenticated) {
                val account = DatabaseStorage.getAccountAndPassword()
                    ?: return
                if (account.key != null && account.value != null)
                    connectLogin(account.key, account.value)
                return
            }
            val isPingSuccess = mPingManager?.pingMyServer(false, 600)
                ?: return
            if (isPingSuccess) {
                LogUtils.e("发送PING：成功")
            } else {
                LogUtils.e("发送PING：失败，重新连接")
                connectAgain()
            }
        }
    }

    /**
     * 重写认证成功监听
     * */
    override fun authenticated(connection: XMPPConnection, resumed: Boolean) {
        wasAuthenticated = false
        super.authenticated(connection, resumed)
        //初始管理类
        initManager(connection)
        //设置在线
        setPresence(0)
    }

    /**
     * 重写关闭连接监听
     * */
    override fun connectionClosed() {
        wasAuthenticated = true
        super.connectionClosed()
        resetMessage()
    }

    /**
     * 重写连接失败监听
     * */
    override fun connectionClosedOnError(e: Exception) {
        wasAuthenticated = true
        super.connectionClosedOnError(e)
        resetMessage()
    }

    /**
     * 初始管理类并注册监听
     *
     * @param connection 连接器
     */
    private fun initManager(connection: XMPPConnection) {

        //实例化花名册管理类并注册监听
        mRosterManager = Roster.getInstanceFor(connection)
        mRosterManager!!.addSubscribeListener(this)
        //mRosterManager!!.addRosterListener(this)
        mRosterManager!!.getEntriesAndAddListener(this, this)

        //实例化聊天管理类并注册监听
        mChatManager = ChatManager.getInstanceFor(connection)
        mChatManager!!.addOutgoingListener(this)
        mChatManager!!.addIncomingListener(this)

        //实例化书签管理类
        mBookmarkManager = BookmarkManager.getBookmarkManager(connection)

        //实例化聊天室管理类并注册监听
        mMucManager = MultiUserChatManager.getInstanceFor(connection)
        mMucManager!!.addInvitationListener(this)

        //默认获取聊天室信息并加入
        getConferenceInfo().forEach {
            this.onBookmarkedConferences(setConferenceJoin(it), Constants.USER_ROOM_SUB_3)
        }

        //实例化PING管理类并注册监听
        mPingManager = PingManager.getInstanceFor(connection)
    }

    /**
     * 复位管理类移除监听
     */
    private fun resetMessage() {
        if (mRosterManager != null) {
            mRosterManager!!.removeSubscribeListener(this)
            mRosterManager!!.removeRosterListener(this)
        }
        if (mChatManager != null) {
            mChatManager!!.removeIncomingListener(this)
            mChatManager!!.removeOutgoingListener(this)
        }
        if (mMucManager != null) {
            mMucManager!!.removeInvitationListener(this)
        }
        for (muc in mMultiUserChatMap.values) {
            muc.removeMessageListener(this)
        }
    }

    /**
     * 判断网络连接是否可用
     * */
    private val isNetworkState: Boolean
        get() {
            val connManager = ImApplication.context()
                .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val networkInfo = connManager.activeNetworkInfo
            return networkInfo != null && networkInfo.isConnected
        }

    /**
     * 判断连接是否成功
     *
     * @return true/false
     */
    private val isConnected: Boolean
        get() = connection != null && connection!!.isConnected

    /**
     * 判断连接是否通过了身份验证
     * 即登录成功
     *
     * @return true/false
     */
    val isAuthenticated: Boolean
        get() = (connection != null && connection!!.isConnected
                && connection!!.isAuthenticated)


    /**
     * 断开连接
     */
    public fun disconnect() {
        if (isConnected) {
            connection!!.disconnect()
        }
    }

    /**
     * 连接登录
     *
     * @param username 账户
     * @param password 密码
     * @return 成功true 失败false
     */
    @Throws(Exception::class)
    fun connectLogin(username: String, password: String): Boolean {
        this.disconnect()
        if (connection == null) {
            throw Exception("AbstractXMPPConnection未初始化")
        }
        this.connectedStart()
        connection!!.connect().login(username, password)
        return connection!!.isAuthenticated
    }

    /**
     * 重新连接
     *
     * @return 成功true 失败false
     */
    @Throws(Exception::class)
    fun connectAgain(): Boolean {
        this.disconnect()
        if (connection == null) {
            throw Exception("AbstractXMPPConnection未初始化")
        }
        this.connectedStart()
        connection!!.connect().login()
        return connection!!.isAuthenticated
    }


    /**
     * 断开连接退出登录
     *
     * @return 成功true 失败false
     */
    fun connectQuit(): Boolean {
        this.disconnect()
        if (mTimerServer != null) {
            mTimerServer?.cancel()
        }
        if (connection != null) {
            connection!!.removeSyncStanzaListener(this)
            connection!!.removeConnectionListener(this)
            connection = null
        }
        if (imConnection != null) {
            imConnection = null
        }
        return true
    }

    /**
     * 更改用户状态
     *
     * @param code 状态标识码
     */
    fun setPresence(code: Int) {
        try {
            if (!isAuthenticated) {
                throw Exception("客户端未连接-认证")
            }
            var presence: Presence? = null
            when (code) {
                0//设置在线
                -> presence = Presence(Presence.Type.available, "在线", 1, Presence.Mode.available)
                1//设置Q我吧
                -> {
                    presence = Presence(Presence.Type.available)
                    presence.mode = Presence.Mode.chat
                }
                2//设置忙碌
                -> {
                    presence = Presence(Presence.Type.available)
                    presence.mode = Presence.Mode.dnd
                }
                3//设置离开
                -> {
                    presence = Presence(Presence.Type.available)
                    presence.mode = Presence.Mode.away
                }
                4//设置离线
                -> presence = Presence(Presence.Type.unavailable)
                else -> {
                }
            }
            if (presence == null) {
                return
            }
            connection!!.sendStanza(presence)
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    /**
     * 更改订阅关系
     *
     * @param code    订阅标识码
     * @param userJid 用户JID
     */
    fun setSubscribe(code: Int, userJid: String?) {
        try {
            if (!isAuthenticated) {
                throw Exception("客户端未连接-认证")
            }
            if (userJid == null || userJid.isEmpty()) {
                throw Exception("userJid用户JID不能为空")
            }
            val jid = JidCreate.from(userJid)
            var presence: Presence? = null
            when (code) {
                0//请求订阅
                -> presence = Presence(jid, Presence.Type.subscribe)
                1//同意订阅
                -> presence = Presence(jid, Presence.Type.subscribed)
                2//取消订阅
                -> presence = Presence(jid, Presence.Type.unsubscribe)
                3//拒绝订阅
                -> presence = Presence(jid, Presence.Type.unsubscribed)
                else -> {
                }
            }
            if (presence == null) {
                return
            }
            connection!!.sendStanza(presence)
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }


    /**
     * 获取账户信息
     *
     * @return Map<String></String>, String> 账户信息
     */
    @Throws(Exception::class)
    fun getAccountAttribute(): Map<String, String> {
        if (!isConnected) {
            throw Exception("客户端未连接-认证")
        }
        val accountManager = AccountManager.getInstance(connection)
        val accountMaps = HashMap<String, String>()
        for (key in accountManager.accountAttributes) {
            accountMaps[key] = accountManager.getAccountAttribute(key)
        }
        accountMaps["jid"] = connection!!.user.asEntityBareJidString()
        return accountMaps
    }

    /**
     * 账户注册
     *
     * @param password 密码
     * @param nickname 用户昵称
     * @return 返回账号
     */
    @Throws(Exception::class)
    fun setAccountCreate(nickname: String?, password: String?): String {
//        if (!isAuthenticated) {
//            throw Exception("客户端未连接-认证")
//        }
        if (connection == null) {
            throw Exception("AbstractXMPPConnection未初始化")
        }
        if (isConnected)
            connection!!.disconnect()
        if (password == null || password.isEmpty()) {
            throw Exception("password密码不能为空")
        }
        if (nickname == null || nickname.isEmpty()) {
            throw Exception("nickname昵称不能为空")
        }
        val accountManager = AccountManager.getInstance(connection!!.connect())
        accountManager.sensitiveOperationOverInsecureConnection(true)
        val account = RandomUntil.getNumLetter(9)
        accountManager.createAccount(
            Localpart.from(account), password,
            mutableMapOf("name" to nickname)
        )
        return account
    }


    /**
     * 获取花名册成员
     */
    @Throws(Exception::class)
    fun getRosterEntries(): Set<RosterEntry> {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        return mRosterManager!!.entries
    }

    /**
     * 获取花名册成员指定jid
     *
     * @param userJid 用户JID
     * @return RosterEntry 用户信息
     */
    @Throws(Exception::class)
    fun getRosterEntries(userJid: String?): RosterEntry? {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (userJid == null || userJid.isEmpty()) {
            throw Exception("userJid用户JID不能为空")
        }
        val jid = JidCreate.bareFrom(userJid)
        return mRosterManager!!.getEntry(jid)
    }

    /**
     * 搜索用户
     *
     * @param answer 搜索内容
     */
    @Throws(Exception::class)
    fun getRosterSearch(answer: String?): List<ReportedData.Row> {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (answer == null || answer.isEmpty()) {
            throw Exception("answer搜索内容不能为空")
        }
        val search = UserSearchManager(connection)
        val domain = JidCreate.domainBareFrom("search.openfire-voc")
        val form = search.getSearchForm(domain).createAnswerForm()
        form.setAnswer("Username", true)
        form.setAnswer("search", answer)
        return search.getSearchResults(form, domain).rows
    }

    /**
     * 添加花名册成员
     *
     * @param userJid  用户JID
     * @param nickname 用户备注名
     * @return boolean 成功true，失败false
     */
    @Throws(Exception::class)
    fun setRosterCreate(userJid: String?, nickname: String?): Boolean {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (userJid == null || userJid.isEmpty()) {
            throw Exception("userJid用户JID不能为空")
        }
        if (nickname == null || nickname.isEmpty()) {
            throw Exception("nickname备注名不能为空")
        }
        val jid = JidCreate.bareFrom(userJid)
        mRosterManager!!.createEntry(jid, nickname, null)
        return true
    }

    /**
     * 判断是否为好友
     *
     * @param userJid 用户JID
     */
    @Throws(Exception::class)
    fun isRosterEntries(userJid: String?): Boolean {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (userJid == null || userJid.isEmpty()) {
            throw Exception("userJid用户JID不能为空")
        }
        val jid = JidCreate.from(userJid)
        return mRosterManager!!.isSubscribedToMyPresence(jid)
    }

    /**
     * 删除花名册成员指定jid
     *
     * @param userJid 用户JID
     * @return boolean 成功true，失败false
     */
    @Throws(Exception::class)
    fun removeRosterEntries(userJid: String?): Boolean {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (userJid == null || userJid.isEmpty()) {
            throw Exception("userJid用户JID不能为空")
        }
        val jid = JidCreate.bareFrom(userJid)
        val entry = mRosterManager!!.getEntry(jid)
        if (entry != null) {
            mRosterManager!!.removeEntry(entry)
        } else {
            val packet = RosterPacket()
            packet.type = IQ.Type.set
            val item = RosterPacket.Item(jid, "")
            item.itemType = RosterPacket.ItemType.remove
            packet.addRosterItem(item)
            connection!!.createStanzaCollectorAndSend(packet).nextResultOrThrow<RosterPacket>()
        }
        return true
    }


    /**
     * 获取书签聊天室
     */
    @Throws(Exception::class)
    fun getConferenceBook(): List<BookmarkedConference> {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        val conferences = mBookmarkManager!!.bookmarkedConferences
        return if (conferences.isEmpty()) {
            ArrayList()
        } else conferences
    }

    /**
     * 加入书签聊天室
     *
     * @param roomInfo 聊天室信息
     */
    @Throws(Exception::class)
    fun setConferenceBook(roomInfo: RoomInfo): RoomInfo {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        mBookmarkManager!!.addBookmarkedConference(
            roomInfo.room.localpart.intern(), roomInfo.room,
            false, Resourcepart.from(Constants.ROOM_NICKNAME), null
        )
        return roomInfo
    }

    /**
     * 移除书签聊天室
     *
     * @param roomInfo 聊天室信息
     */
    @Throws(Exception::class)
    fun removeConferenceBook(roomInfo: RoomInfo) {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        mBookmarkManager!!.removeBookmarkedConference(roomInfo.room)
    }

    /**
     * 获取聊天室信息
     *
     * @return List<RoomInfo>
    </RoomInfo> */
    @Throws(Exception::class)
    fun getConferenceInfo(): List<RoomInfo> {
        val conferences = getConferenceBook()
        if (conferences.isEmpty()) {
            return ArrayList()
        }
        val roomInfos = ArrayList<RoomInfo>()
        for (conference in conferences) {
            roomInfos.add(getConferenceInfo(conference.jid.intern()))
        }
        return roomInfos
    }

    /**
     * 获取聊天室信息(通过聊天室jid)
     *
     * @param roomJid 聊天室JID
     * @return roomInfo 聊天室信息
     */
    @Throws(Exception::class)
    fun getConferenceInfo(roomJid: String?): RoomInfo {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (roomJid == null || roomJid.isEmpty()) {
            throw Exception("roomJid聊天室JID不能为空")
        }
        val jid = JidCreate.entityBareFrom(roomJid)
        return mMucManager!!.getRoomInfo(jid)
    }


    /**
     * 创建聊天室
     *
     * @param roomName 房间名称
     * @return roomInfo 聊天室信息
     */
    @Throws(Exception::class)
    fun setConferenceCreate(roomName: String): RoomInfo {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        //生成聊天室Jid
        val roomJid = StringBuilder(RandomUntil.getNumLargeSmallLetter(9))
            .append("@").append(Constants.XMPP_SERVICE_ROOM)
        val jid = JidCreate.entityBareFrom(roomJid)
        //创建聊天室
        val muc = mMucManager!!.getMultiUserChat(jid)
        muc.create(Resourcepart.from(Constants.ROOM_NICKNAME))
        //重新配置聊天室
        val form = muc.configurationForm
        val submitForm = form.createAnswerForm()
        for (field in form.fields) {
            if (field.variable != null && field.type != FormField.Type.hidden)
                submitForm.setDefaultAnswer(field.variable)
        }
        submitForm.setAnswer("muc#roomconfig_roomname", roomName)
        submitForm.setAnswer("muc#roomconfig_persistentroom", true)
        submitForm.setAnswer("muc#roomconfig_membersonly", false)
        submitForm.setAnswer("muc#roomconfig_allowinvites", true)
        submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", false)
        submitForm.setAnswer("muc#roomconfig_whois", arrayListOf("anyone"))
        submitForm.setAnswer("muc#roomconfig_enablelogging", true)
        submitForm.setAnswer("x-muc#roomconfig_reservednick", true)
        submitForm.setAnswer("x-muc#roomconfig_canchangenick", true)
        submitForm.setAnswer("x-muc#roomconfig_registration", true)
        //发送聊天室配置
        muc.sendConfigurationForm(submitForm)

        return mMucManager!!.getRoomInfo(muc.room)
    }

    /**
     * 加入聊天室
     *
     * @param roomInfo 聊天室信息
     */
    @Throws(Exception::class)
    fun setConferenceJoin(roomInfo: RoomInfo): RoomInfo {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        val muc = mMucManager!!.getMultiUserChat(roomInfo.room)
        val nickname = Resourcepart.from(Constants.ROOM_NICKNAME)
        val builder = muc.getEnterConfigurationBuilder(nickname)

        val userRoom = DatabaseStorage.getUserRoomStorageByAccount(roomInfo.room.localpart.intern())
        if (userRoom == null) {
            builder.requestHistorySince(0)
        } else {
            val chatEntry = DatabaseStorage.getChatLastId(userRoom.id)
            if (chatEntry == null) {
                builder.requestHistorySince(0)
            } else {
                builder.requestHistorySince(Date(chatEntry.chatRecord?.time!!.toLong() + 1000))
            }
        }
        muc.leave()
        muc.join(builder.build())

        if (muc.owners.none {
                it.jid.intern() == DatabaseStorage.getAccountInfoStorage().jid
            }) {
            //离开聊天室
            muc.leave()
            //移除书签
            removeConferenceBook(roomInfo)
            //
            onOwnershipRevoked(roomInfo)
        } else {
            muc.addMessageListener(this)
            val userStatusListener = object : DefaultUserStatusListener() {
                override fun ownershipRevoked() {
                    super.ownershipRevoked()
                    val roomId = muc.room.localpart.intern()
                    //移除群消息监听
                    muc.removeMessageListener(imConnection)
                    //离开聊天室
                    muc.leave()
                    //移除MUC Map数据
                    mMultiUserChatMap.remove(roomId)
                    //移除用户状态监听
                    muc.removeUserStatusListener(this)
                    //移除书签
                    removeConferenceBook(roomInfo)
                    //
                    onOwnershipRevoked(roomInfo)
                }
            }
            muc.removeUserStatusListener(userStatusListener)
            muc.addUserStatusListener(userStatusListener)
            mMultiUserChatMap[roomInfo.room.localpart.intern()] = muc
        }

        return roomInfo
    }

    /**
     * 退出群聊
     * */
    fun setConferenceExit(roomName: String, roomJid: String): Boolean {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        val jid = JidCreate.entityBareFrom(roomJid)
        val muc = mMultiUserChatMap[roomName]
            ?: return true
        if (muc.owners.size == 1) {
            muc.removeMessageListener(this)
            muc.destroy("", jid)
            mMultiUserChatMap.remove(roomName)
        } else {
            val userJid = JidCreate.entityBareFrom(
                DatabaseStorage.getAccountInfoStorage().jid
            )
            muc.revokeMembership(userJid)
        }
        mBookmarkManager!!.removeBookmarkedConference(jid)

        return true
    }

    /**
     * 被踢除主持人身份
     * */
    fun roomKickCover(roomId: String) {
        val muc = mMultiUserChatMap[roomId]
            ?: return
        //移除群消息监听
        muc.removeMessageListener(this)
        //离开聊天室
        muc.leave()
        //
        mMultiUserChatMap.remove(roomId)
    }

    /**
     * 邀请好友
     *
     * @param roomId 聊天室ID
     * @param owners 需要邀请的成员
     * @return 成功true，失败false
     */
    @Throws(Exception::class)
    fun setConferenceInvite(roomId: String?, owners: List<String>): Boolean {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (roomId == null || roomId.isEmpty()) {
            throw Exception("roomId聊天室ID不能为空")
        }
        val muc = mMultiUserChatMap[roomId] ?: return false
        if (owners.isEmpty()) {
            throw Exception("owners请选择邀请好友")
        }
        for (jid in owners) {
            muc.grantOwnership(JidCreate.from(jid))
            muc.invite(JidCreate.entityBareFrom(jid), null)
        }
        return true
    }


    /**
     * 踢除群成员
     *
     * @param roomId  聊天室ID
     * @param userJid 用户JID
     * @return 成功true，失败false
     */
    @Throws(Exception::class)
    fun setConferenceKick(roomId: String?, userJid: String?): Boolean {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        if (roomId == null || roomId.isEmpty()) {
            throw Exception("roomId聊天室ID不能为空")
        }
        if (userJid == null || userJid.isEmpty()) {
            throw Exception("userJid用户Jid不能为空")
        }
        val muc = mMultiUserChatMap[roomId] ?: return false
        val jid = JidCreate.from(userJid)
        muc.revokeMembership(jid)
        return true
    }

    /**
     * 获取聊天室成员
     *
     * @param roomId 聊天室ID
     * @return List<Affiliate> 成员集合信息
    </Affiliate> */
    @Throws(Exception::class)
    fun getConferenceOwners(roomId: String): List<Affiliate> {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        val muc = mMultiUserChatMap[roomId] ?: return ArrayList()
        return muc.owners ?: return ArrayList()
    }

    /**
     * 判断是否为房间成员
     *
     * @param roomId  聊天室ID
     * @param userJid 用户JID
     */
    @Throws(Exception::class)
    fun isConferenceOwners(roomId: String, userJid: String): Boolean {
        val affiliates = getConferenceOwners(roomId)
        if (affiliates.isEmpty()) {
            return false
        }
        for (affiliate in affiliates) {
            if (affiliate.jid.intern() == userJid) {
                return true
            }
        }
        return false
    }

    /**
     * 发送消息
     *
     * @param userJid 用户JID
     * @param body    消息内容
     * @param type    类型 单聊（Message.Type.chat == 1），群聊（Message.Type.groupchat == 2）
     */
    @Throws(Exception::class)
    fun sendChatMessage(userJid: String, type: Message.Type, body: String): Boolean {
        if (!isAuthenticated) {
            throw Exception("客户端未连接-认证")
        }
        val jid = JidCreate.entityBareFrom(userJid)
        val message = Message()
        message.body = body
        message.type = type
        when (type) {
            Message.Type.chat -> {
                mChatManager!!.chatWith(jid).send(message)
            }
            Message.Type.groupchat -> {
                val muc = mMultiUserChatMap[jid.localpart.intern()]
                    ?: return false
                muc.sendMessage(message)
            }
            else -> throw Exception("type类型错误")
        }
        return true
    }

    companion object {

        @Volatile
        private var imConnection: IMConnection? = null

        val instance: IMConnection?
            get() {
                if (imConnection == null)
                    synchronized(IMConnection::class.java) {
                        if (imConnection == null)
                            imConnection =
                                IMConnection()
                    }
                return imConnection
            }
    }

}
